"""
模拟OA系统API服务
提供审批、考勤等API接口
"""
from fastapi import FastAPI, HTTPException, Depends, Header
from typing import List, Optional, Dict, Any
from datetime import datetime, timedelta
import uvicorn
from pydantic import BaseModel
import jwt
from fastapi.middleware.cors import CORSMiddleware
import random

# 创建FastAPI应用
app = FastAPI(title="模拟OA系统API")

# 配置CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# JWT配置
SECRET_KEY = "oa_demo_secret_key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

# 模拟数据库
users_db = {
    "zhangsan": {
        "username": "zhangsan",
        "full_name": "张三",
        "email": "zhangsan@example.com",
        "hashed_password": "fakehashedpassword",
        "department": "技术部",
        "position": "开发工程师"
    },
    "lisi": {
        "username": "lisi",
        "full_name": "李四",
        "email": "lisi@example.com",
        "hashed_password": "fakehashedpassword",
        "department": "人力资源部",
        "position": "HR专员"
    },
    "wangwu": {
        "username": "wangwu",
        "full_name": "王五",
        "email": "wangwu@example.com",
        "hashed_password": "fakehashedpassword",
        "department": "财务部",
        "position": "财务经理"
    }
}

# 模拟审批单据
approval_documents = [
    {
        "id": "AP20231001001",
        "title": "服务器采购申请",
        "type": "采购申请",
        "applicant": "zhangsan",
        "department": "技术部",
        "submit_time": "2023-10-01 09:30:00",
        "status": "待审批",
        "current_approver": "wangwu",
        "amount": 50000.00,
        "content": "申请购买2台高性能服务器用于项目部署",
        "urgency": "高"
    },
    {
        "id": "AP20231005002",
        "title": "市场推广费用报销",
        "type": "费用报销",
        "applicant": "lisi",
        "department": "市场部",
        "submit_time": "2023-10-05 14:20:00",
        "status": "待审批",
        "current_approver": "wangwu",
        "amount": 8500.00,
        "content": "9月份市场推广活动费用报销",
        "urgency": "中"
    },
    {
        "id": "AP20231010003",
        "title": "年假申请",
        "type": "休假申请",
        "applicant": "zhangsan",
        "department": "技术部",
        "submit_time": "2023-10-10 11:00:00",
        "status": "已审批",
        "current_approver": None,
        "amount": None,
        "content": "申请11月1日至11月5日休年假5天",
        "urgency": "低"
    }
]

# 模拟考勤记录
attendance_records = {}

# 生成一个月的考勤记录
def generate_attendance_records(username, year, month):
    if username not in users_db:
        return []
    
    records = []
    # 获取当月天数
    if month in [4, 6, 9, 11]:
        days_in_month = 30
    elif month == 2:
        if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
            days_in_month = 29
        else:
            days_in_month = 28
    else:
        days_in_month = 31
    
    for day in range(1, days_in_month + 1):
        date_str = f"{year}-{month:02d}-{day:02d}"
        # 周末不记考勤
        date_obj = datetime.strptime(date_str, "%Y-%m-%d")
        if date_obj.weekday() >= 5:  # 5和6是周六和周日
            continue
        
        # 随机生成考勤状态
        status_options = ["正常", "迟到", "早退", "缺勤", "请假"]
        weights = [0.8, 0.1, 0.05, 0.03, 0.02]
        status = random.choices(status_options, weights=weights)[0]
        
        # 根据状态生成打卡时间
        if status == "正常":
            check_in = f"{date_str} 08:{random.randint(30, 59)}:00"
            check_out = f"{date_str} 18:{random.randint(0, 30)}:00"
        elif status == "迟到":
            check_in = f"{date_str} 09:{random.randint(10, 59)}:00"
            check_out = f"{date_str} 18:{random.randint(0, 30)}:00"
        elif status == "早退":
            check_in = f"{date_str} 08:{random.randint(30, 59)}:00"
            check_out = f"{date_str} 17:{random.randint(0, 30)}:00"
        elif status == "缺勤":
            check_in = None
            check_out = None
        else:  # 请假
            check_in = None
            check_out = None
        
        record = {
            "username": username,
            "date": date_str,
            "check_in": check_in,
            "check_out": check_out,
            "status": status
        }
        records.append(record)
    
    return records

# 模型定义
class Token(BaseModel):
    access_token: str
    token_type: str

class TokenData(BaseModel):
    username: Optional[str] = None

class User(BaseModel):
    username: str
    email: Optional[str] = None
    full_name: Optional[str] = None
    department: Optional[str] = None
    position: Optional[str] = None

class UserInDB(User):
    hashed_password: str

class LoginRequest(BaseModel):
    username: str
    password: str

# 认证相关函数
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

def get_user(db, username: str):
    if username in db:
        user_dict = db[username]
        return UserInDB(**user_dict)
    return None

async def get_current_user(authorization: str = Header(None)):
    credentials_exception = HTTPException(
        status_code=401,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    if not authorization:
        raise credentials_exception
    
    scheme, token = authorization.split()
    if scheme.lower() != "bearer":
        raise credentials_exception
    
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except jwt.PyJWTError:
        raise credentials_exception
    
    user = get_user(users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user

# API路由
@app.post("/token", response_model=Token)
async def login_for_access_token(login_request: LoginRequest):
    user = get_user(users_db, login_request.username)
    if not user:
        raise HTTPException(
            status_code=401,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    # 简化示例，不做实际密码验证
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}

@app.get("/users/me", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_user)):
    return current_user

@app.get("/approvals/pending")
async def get_pending_approvals(current_user: User = Depends(get_current_user)):
    """获取待审批的单据"""
    result = []
    for doc in approval_documents:
        if doc["current_approver"] == current_user.username and doc["status"] == "待审批":
            result.append(doc)
    return {"total": len(result), "items": result}

@app.get("/approvals/my")
async def get_my_approvals(current_user: User = Depends(get_current_user)):
    """获取我提交的单据"""
    result = []
    for doc in approval_documents:
        if doc["applicant"] == current_user.username:
            result.append(doc)
    return {"total": len(result), "items": result}

@app.get("/attendance/my")
async def get_my_attendance(
    year: int, 
    month: int, 
    current_user: User = Depends(get_current_user)
):
    """获取我的考勤记录"""
    key = f"{current_user.username}_{year}_{month}"
    if key not in attendance_records:
        # 首次访问时生成考勤记录
        attendance_records[key] = generate_attendance_records(current_user.username, year, month)
    
    records = attendance_records[key]
    
    # 统计考勤情况
    stats = {
        "normal": len([r for r in records if r["status"] == "正常"]),
        "late": len([r for r in records if r["status"] == "迟到"]),
        "early_leave": len([r for r in records if r["status"] == "早退"]),
        "absent": len([r for r in records if r["status"] == "缺勤"]),
        "leave": len([r for r in records if r["status"] == "请假"]),
        "total": len(records)
    }
    
    return {
        "year": year,
        "month": month,
        "username": current_user.username,
        "records": records,
        "statistics": stats
    }

@app.get("/")
async def root():
    return {"message": "OA系统API服务"}

if __name__ == "__main__":
    uvicorn.run("mock_oa_api:app", host="127.0.0.1", port=8000, reload=True)